﻿using RFIDReaderDll; 
using smforj.common.model;
using smforj.common.service;
using smforj.common.util; 
using System;
using System.Collections.Generic;
using System.Configuration;
using System.Linq;
using System.Text;
using System.Threading;

namespace MonitorEquipmentFrm
{
    /// <summary>
    /// 安全门监控实现类，该对象需要app.config配置参数
    /// </summary>
    public class MonitorZDHKWardrobeImpl :IMonitor
    {
        #region 变量
        private LogManage log = new LogManage();
        private IWardRobeService wardRobeService; 
        /// <summary>
        /// client 对象
        /// </summary>
        private IMonitorClient monitorClient = null;
        /// <summary>
        /// 设备信息
        /// </summary>
        private EquementInfo equement = null; 
        /// <summary>
        /// RFID控制类
        /// </summary>
        private RFIDClient reader = null;
        /// <summary>
        /// 数据区操作对象
        /// </summary>
        private OperatReader opreader = null;
        /// <summary>
        /// 是否连接设备
        /// </summary>
        private Boolean isOpen = false;
        private Boolean isReading = false;
        /// <summary>
        /// 消息队列
        /// </summary>
        private List<WardRobe> queue = new List<WardRobe>();
        /// <summary>
        /// 初始标签信息
        /// </summary>
        private List<Tag> baseQueue = new List<Tag>();

        /// <summary>
        /// 线程阻塞
        /// </summary>
        private bool IsGetting = false;
        /// <summary>
        /// 读取数据线程
        /// </summary>
        private AutoResetEvent myResetRead = new AutoResetEvent(false);
        /// <summary>
        /// 上传数据线程
        /// </summary>
        private AutoResetEvent myResetUpload = new AutoResetEvent(false); 
         
        /// <summary>
        /// 监控线程
        /// </summary>
        Thread thread = null;
        /// <summary>
        /// 数据读取线程
        /// </summary>
        Thread threadRead = null;


        private String message = "";
        private String error = "";
        private int istatus = 0;

        #endregion


        public MonitorZDHKWardrobeImpl()
        {
            init();
        }
        /// <summary>
        /// 初始化参数
        /// </summary>
        public void init()
        {
            wardRobeService = new DxtWardRobeServiceImpl();
        }
        
        #region 读卡器操作
        private void AutoConnect()
        {
            UpdateMessage(InfoType.Info,String.Format("启动{0}服务...",this.equement.IConnConfig.Ip));
            reader = new RFIDClient();
            reader.OnDisconnect += new EventHandler<DisconnectEventArgs>(reader_OnDisconnect);
            reader.OnErrorcallback += new EventHandler<ErrorReportEventArgs>(reader_OnErrorcallback);
            reader.OnInventoryReport += new EventHandler<InventoryReportEventArgs>(reader_OnInventoryReport);
            try
            {
                String ip = this.equement.IConnConfig.Ip;
                String port = this.equement.IConnConfig.Port;
                reader.Connect(ip, (ushort)Convert.ToInt32(port));
                //设置天线
                //SetAntena();
                //不再使用盘点因为其只能在读取到数据时才上传
                //int iRes = reader.StartPerioInventory();
                //isOpen = iRes == 0 ? true : false;
                isOpen = true;
                opreader = reader; 
                UpdateMessage(InfoType.Info, String.Format("{0}服务状态isOpen：{1}", this.equement.IConnConfig.Ip,isOpen));
            }
            catch (Exception ex)
            {
                error = String.Format("启动{0}服务异常：{1}",this.equement.IConnConfig.Ip,ex.Message);
                UpdateMessage(InfoType.Error, error);
                log.Error(error);
                isOpen = false;
                istatus = -1;
            }
            UpdateMessage(InfoType.Info, String.Format("启动{0}服务...end ", this.equement.IConnConfig.Ip));
        }

        /// <summary>
        /// 关闭设备
        /// </summary>
        private void AutoDisconnect()
        {
            UpdateMessage(InfoType.Info,String.Format("停止{0}服务...",this.equement.IConnConfig.Ip));
            try
            {  
                if (isOpen)
                {
                    isStopChecking = true;
                    isReading = false; 
                    //int iRes = reader.StopPeriodInventory();
                    //UpdateMessage(InfoType.Info, String.Format("StopPeriodInventory：{0}", iRes));
                    reader.Disconnect(); 
                    //等待数据处理线程
                    myResetRead.WaitOne(5000);
                    myResetUpload.WaitOne(5000); 
                    UpdateMessage(InfoType.Info, String.Format("{0}服务状态isOpen：{1}", this.equement.IConnConfig.Ip, isOpen));

                    if (null != threadRead) threadRead.Abort();
                    if (null != thread) thread.Abort();
                }
                istatus = 0; 
            }
            catch (Exception ex)
            {
                error = String.Format("关闭服务异常：{0}",ex.Message);
                UpdateMessage(InfoType.Error, error);
                log.Error(error);
                istatus = 1;
            }
            finally
            {
                opreader = reader = null;
                queue.Clear();
                baseQueue.Clear();
                testCount = 0;
                isStopChecking = false;  
                isOpen = false;
                initData = 5;
                GC.Collect();
            }
            UpdateMessage(InfoType.Info, String.Format("停止{0}服务...end", this.equement.IConnConfig.Ip, isOpen));
        }   

                
        private void SetAntena()
        {
            if (reader == null)
                return;
            //log.Info("正在设置天线");
            //获取状态
            DEVICE_ANAINFO_STATUS_RESULT status = new DEVICE_ANAINFO_STATUS_RESULT();
            SET_ALLANTENNA_PARAM antena = new SET_ALLANTENNA_PARAM();
            int ret = reader.GetAntena(ref status);
            if (0 == ret)
            {

                antena.ant1.bEnable = status.AnaStatus == "1" ? true : false;
                antena.ant2.bEnable = status.AnaStatus2 == "1" ? true : false;
                antena.ant3.bEnable = status.AnaStatus3 == "1" ? true : false;
                antena.ant4.bEnable = status.AnaStatus4 == "1" ? true : false;

                antena.ant1.nPower = Convert.ToInt32(status.TransmitPower);
                antena.ant2.nPower = Convert.ToInt32(status.TransmitPower2);
                antena.ant3.nPower = Convert.ToInt32(status.TransmitPower3);
                antena.ant4.nPower = Convert.ToInt32(status.TransmitPower4);

                antena.ant1.nDwellTime = Convert.ToInt32(status.DwellTime);
                antena.ant2.nDwellTime = Convert.ToInt32(status.DwellTime2);
                antena.ant3.nDwellTime = Convert.ToInt32(status.DwellTime3);
                antena.ant4.nDwellTime = Convert.ToInt32(status.DwellTime4);

                antena.ant1.nInvCycle = Convert.ToInt32(status.NumInvCyc);
                antena.ant2.nInvCycle = Convert.ToInt32(status.NumInvCyc2);
                antena.ant3.nInvCycle = Convert.ToInt32(status.NumInvCyc3);
                antena.ant4.nInvCycle = Convert.ToInt32(status.NumInvCyc4);

            }

            antena.ant1.nPower = Convert.ToInt32(equement.Ant1);
            antena.ant2.nPower = Convert.ToInt32(equement.Ant2);
            antena.ant3.nPower = Convert.ToInt32(equement.Ant3);
            antena.ant4.nPower = Convert.ToInt32(equement.Ant4);

            reader.SetAntenna(ref antena);
            //log.Info("正在天线完成");
        }
        #endregion

        #region 事件处理

        /// <summary>
        /// 
        /// 多次盘点进行一次数据校验
        /// 盘点多次读取到的标签数据进行合并，重复的去除，多余的添加
        /// </summary>
        private List<Tag> temp = new List<Tag>();
        private int initCount = 10;
        private long testCount = 0;
        /// <summary>
        /// 该方法只有读取到盘点数据时才被调用
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void reader_OnInventoryReport(object sender, InventoryReportEventArgs e)
        {
            try
            {
                isReading = true;
                testCount++;
                TagReport report = e.Report;
                if (initCount-- > 0)
                {
                    temp.AddRange(report.Tags);
                    return;
                }
                if (baseQueue.Count == 0)
                {
                    baseQueue.AddRange(temp.Where((x, i) => temp.FindIndex(z => z.Epc == x.Epc) == i).ToList());//Lambda表达式去重  ); 
                    temp.Clear();
                    return;
                }
                //三次盘点做为一次比对消息
                if (temp.Count <= 3)
                    temp.AddRange(report.Tags);
                else
                { 
                    temp = temp.Where((x, i) => temp.FindIndex(z => z.Epc == x.Epc) == i).ToList(); 
                    foreach (Tag tag in baseQueue)
                    { 
                        Tag t = temp.Find(delegate(Tag _tag) { return _tag.Epc == tag.Epc; });
                        //存在则更新时间
                        if (t != null)
                        {
                            tag.TimeStamp = t.TimeStamp;
                        }
                        else//否则处理消失事件
                        {
                            lock (queue)
                            {
                                WardRobe wr = queue.Find(delegate(WardRobe _wr) { return _wr.RFID == tag.Epc; });
                                if (wr == null)
                                {
                                    queue.Add(new WardRobe()
                                    {
                                        RFID = tag.Epc,
                                        FirstReadTime = Convert.ToDateTime(tag.TimeStamp),
                                        ReadTime = DateTime.Now,
                                        ReaderIdentity = tag.ReaderIdentity,
                                        Loaction = equement.IConnConfig.Location
                                    });
                                }
                                else
                                {
                                    //一直消失中，更新读取时间
                                    if (wr.FirstReadTime.CompareTo(Convert.ToDateTime(tag.TimeStamp)) >= 0)
                                        wr.ReadTime = DateTime.Now; 
                                }
                            }
                        } 
                    }
                    temp.Clear();
                }
            }
            catch (Exception ex)
            {
                error = "reader_OnInventoryReport异常：" + ex.Message;
                UpdateMessage(InfoType.Error, error);
                log.Error("reader_OnInventoryReport异常：" + ex.Message);
            }
        } 

        private void reader_OnErrorcallback(object sender, ErrorReportEventArgs e)
        {
            error = "读取异常：" + e.ReaderIdentity + "  Error Code ：" + e.ErrorCode + "   Mac Error:" + e.MacError;
            UpdateMessage(InfoType.Error, error);
            log.Error(error);
            reader = null;
        }

        private void reader_OnDisconnect(object sender, DisconnectEventArgs e)
        {
            error = String.Format("{0}读写器断开", this.equement.IConnConfig.Ip, isOpen);
            UpdateMessage(InfoType.Error, error);
            log.Error(error); 
            reader = null;
        }

        #endregion

        #region 主业务方法
        private Boolean isStopChecking = false;
        private List<Tag> MTags = new List<Tag>();
        private int initData = 5;
        /// <summary>
        /// 读取EPC信息并剔除重复数据
        /// </summary>
        /// <returns></returns>
        private List<Tag> ReadTag()
        {
         
            TagReport report = null;
            List<Tag> list = new List<Tag>();
            if (opreader == null)
                return list;
            switch (this.equement.AntnnaNumber)
            {
                case 0:
                case 1:
                case 2:
                case 3:
                    report = opreader.InventoryCycle(this.equement.AntnnaNumber);
                    list = report.Tags;
                    break;
                case -1:
                case 1234:
                    report = opreader.InventoryCycle(-1);
                    list = report.Tags;
                    break;
                case 12:
                    report = opreader.InventoryCycle(1);
                    list.AddRange(report.Tags);
                    report = opreader.Inventory(2);
                    list.AddRange(report.Tags);
                    break;
                case 123:
                    report = opreader.InventoryCycle(1);
                    list.AddRange(report.Tags);
                    report = opreader.InventoryCycle(2);
                    list.AddRange(report.Tags);
                    report = opreader.InventoryCycle(3);
                    list.AddRange(report.Tags);
                    break; 
            }
            if (list.Count > 1)
            {
                list = list.Where((x, i) => list.FindIndex(z => z.Epc == x.Epc) == i).ToList();
                foreach (Tag tag in list)
                    tag.Epc = tag.Epc.ToUpper();
            }

            return list;
        }

        /// <summary>
        /// 读取数据
        /// </summary>
        private void ReadData()
        {
            while (!isStopChecking)
            {
                if (opreader == null)
                    break;
                Thread.Sleep(GlobalCache.RTimeSpan);
                try
                {
                    isReading = true;
                    testCount++; 
                    if (initData > 0)
                    {
                        //初始化标签信息,读取5次为校验数据
                        List<Tag> ttt = ReadTag();
                        if (ttt.Count > 0)
                        {
                            initData--;
                            temp.AddRange(ReadTag()); 
                        }
                        continue;
                    }
                    if (baseQueue.Count == 0)
                    {
                        baseQueue.AddRange(temp.Where((x, i) => temp.FindIndex(z => z.Epc == x.Epc) == i).ToList());//Lambda表达式去重  ); 
                        temp.Clear();
                        continue;
                    } 

                    //处理标签
                    temp = ReadTag();
                    if (temp.Count > 0)
                    {
                        DateTime date = DateTime.Now;
                        foreach (Tag tag in baseQueue)
                        {
                            Tag t = temp.Find(delegate(Tag _tag) { return _tag.Epc == tag.Epc; });
                            //存在则更新时间
                            if (t != null)
                            {
                                //如果已经存在数据库中且时间没有超过有效时间间隔慢更新消失时间,代表没有消失
                                lock (queue)
                                {
                                    if (queue.Count > 0)
                                    {
                                        WardRobe wr = queue.Find(delegate(WardRobe _wr) { return _wr.RFID == t.Epc; });
                                        if (wr != null)
                                        {
                                            //再次读取到则将其放入初始状态
                                            wr.FirstReadTime = wr.ReadTime = date;
                                            wr.IsUpload = 0;
                                        }
                                    }
                                }
                                //没有用，设备的时间不准确
                                tag.TimeStamp = t.TimeStamp;
                            }
                            else//否则处理消失事件
                            {
                                lock (queue)
                                {
                                    WardRobe wr = queue.Find(delegate(WardRobe _wr) { return _wr.RFID == tag.Epc; });
                                    if (wr == null)
                                    {
                                        queue.Add(new WardRobe()
                                        {
                                            RFID = tag.Epc,
                                            FirstReadTime = date,
                                            ReadTime = date,
                                            Ant = tag.AntennaPortNumber.ToString(),
                                            ReaderIdentity = tag.ReaderIdentity,
                                            Loaction = equement.IConnConfig.Location,
                                            IsUpload = 0
                                        });
                                    }
                                    else
                                    {
                                        //一直消失中，更新读取时间 
                                        wr.ReadTime = date;
                                    }
                                }
                            }
                        }
                        //清空temp
                        temp.Clear();
                    }
                    else//全部消失
                    {
                        DateTime date = DateTime.Now;
                        foreach (Tag tag in baseQueue)
                        { 
                            lock (queue)
                            {
                                WardRobe wr = queue.Find(delegate(WardRobe _wr) { return _wr.RFID == tag.Epc; });
                                if (wr == null)
                                {
                                    queue.Add(new WardRobe()
                                    {
                                        RFID = tag.Epc,
                                        FirstReadTime = date,
                                        ReadTime = date,
                                        Ant = tag.AntennaPortNumber.ToString(),
                                        ReaderIdentity = tag.ReaderIdentity,
                                        Loaction = equement.IConnConfig.Location,
                                        IsUpload = 0
                                    });
                                }
                                else
                                {
                                    //一直消失中，更新读取时间 
                                    wr.ReadTime = date;
                                }
                            } 
                        }
                    }
                }
                catch (Exception ex)
                {
                    error = "reader_OnInventoryReport异常：" + ex.Message;
                    UpdateMessage(InfoType.Error, error);
                    log.Error("reader_OnInventoryReport异常：" + ex.Message); 
                }  
            }
            isReading = false;
            myResetRead.Set();
        }
        /// <summary>
        /// 业务处理方法
        /// </summary>
        private void CheckData()
        {
            while (!isStopChecking)
            {
                Thread.Sleep(100 * GlobalCache.UTimeSpan);
                if (!IsGetting)
                {
                    IsGetting = true;
                    try
                    { 
                        lock (queue)
                        {
                            UpdateMessage(InfoType.Info, "isReading：" + isReading + " testCount: " + testCount); 

                            UpdateMessage(InfoType.Info, "baseQueue数量：" + baseQueue.Count);  
                            //查看是否要执行凤鸣
                            UpdateMessage(InfoType.Info, "queue数量：" + queue.Count);

                            if (queue.Count > 0)
                            {  
                                List<WardRobe> temp = new List<WardRobe>(); 
                                foreach (WardRobe wr in queue)
                                {   
                                    //有效数据
                                    int accessTime = (int)wr.ReadTime.Subtract(wr.FirstReadTime).TotalSeconds;
                                    UpdateMessage(InfoType.Info, "数据" + wr.RFID + "    " + wr.IsUpload + "    " + wr.FirstReadTime + "    " + wr.ReadTime + "   " + accessTime);
                                    //通知显示消失信息 
                                    //一直消失的数据只保存一份
                                    if (accessTime > GlobalCache.TTimeSpan && wr.IsUpload == 0)
                                    {
                                        wr.IsUpload = 1;
                                        wr.Holdtime = accessTime;
                                        temp.Add(wr);
                                    }
                                }
                                //保存通知显示消失 
                                if (temp.Count > 0)
                                {
                                    wardRobeService.SaveShowToLocalBatch(temp);
                                    UpdateMessage(InfoType.Info, "通知数据............."); 
                                    //wardRobeService.SaveToLocalBatch(temp);
                                    //UpdateMessage(InfoType.Info, "上传数据.............");  
                                    //queue.Clear();
                                }
                            }
                        }
                    }
                    catch (Exception ex)
                    {
                        error = "处理信息异常：" + ex.Message;
                        UpdateMessage(InfoType.Error, error);
                        log.Error(error); 
                    }
                    IsGetting = false;
                } 
            }
            myResetUpload.Set();
        }
        
        private void UpdateMessage(InfoType type, String message)
        {
            if (!isStopChecking) 
                monitorClient.UpdateMessage(new Info() { message = message, type = type},this); 
        }
        #endregion

        #region public Methods

        public string GetError()
        {
            return error;
        }

        public int GetStatus()
        {
            return istatus;
        }

        /// <summary>
        /// 启动服务
        /// </summary>
        /// <returns>0 成功 其他 失败</returns>
        public int StartServer()
        {
            //开户安全门
            AutoConnect();
            if (isOpen)
            {
                threadRead = new Thread(new ThreadStart(ReadData));
                threadRead.Start();

                thread = new Thread(new ThreadStart(CheckData));
                thread.Start(); 
            }
            return isOpen ? 0 : -1;
        } 

        /// <summary>
        /// 停止服务
        /// </summary>
        /// <returns></returns>
        public int StopServer()
        { 
            AutoDisconnect();  
            return isOpen ? -1 : 0;
        }

        public string GetMessage()
        {
            return message;
        }
        #endregion 

        /// <summary>
        /// 获取设备配置信息
        /// </summary>
        /// <returns></returns>
        public EquementInfo GetEquementInfo()
        {
            return this.equement;
        }
        /// <summary>
        /// 设置monitorClient
        /// </summary>
        /// <param name="monitorClient"></param>
        public void SetMonitorClient(IMonitorClient monitorClient)
        {
            this.monitorClient = monitorClient;
        }

        public void SetEquementInfo(EquementInfo equement)
        {
            this.equement = equement;
        }
    }
}
